package com.leyou.item.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.constants.MQConstants;
import com.leyou.item.dto.*;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.GoodsMapper;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.service.IBrandService;
import com.leyou.item.service.ICategoryService;
import com.leyou.item.service.IGoodsService;
import com.leyou.test.enums.ExceptionEnum;
import com.leyou.test.exceptions.LyException;
import com.leyou.utils.BeanHelper;
import com.leyou.vo.PageResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
import tk.mybatis.mapper.entity.Example;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class GoodsServiceImpl implements IGoodsService {
    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private ICategoryService categoryService;

    @Autowired
    private IBrandService brandService;

    @Autowired
    private SpuDetailMapper spuDetailMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;


    /**
     * 分页查询商品
     * @param key
     * @param saleable
     * @param page
     * @param rows
     * @return
     */
    @Override
    public PageResult<SpuDTO> querySpuByPage(String key, Boolean saleable, Integer page, Integer rows) {
        //开启分页
        PageHelper.startPage(page, rows);
        //搜索过滤
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNoneBlank(key)) {
            criteria.andLike("name", "%"+key+"%");
        }
        //上架过滤
        if (null != saleable) {
            criteria.andEqualTo("saleable", saleable);
        }
        //按时间排序
//        String orderByClause = "ORDER BY createTime DESC";
//        example.setOrderByClause(orderByClause);

        //进行查询
        List<Spu> spus = goodsMapper.selectByExample(example);

        //对分页查询结果进行封装
        PageInfo<Spu> pageInfo = new PageInfo<>(spus);

        List<SpuDTO> spuDTOS = BeanHelper.copyWithCollection(spus, SpuDTO.class);

        //将categoryName和brandName封装进SpuDTO中
        handleCategoryAndBrand(spuDTOS);

        return new PageResult<>(pageInfo.getTotal(), pageInfo.getPages(),spuDTOS);
    }

    /**
     * 新增商品
     * @param spuDTO
     */
    @Transactional
    @Override
    public void saveGoods(SpuDTO spuDTO) {
        //新增spu
        Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
        int count = goodsMapper.insertSelective(spu);
        if (1 != count) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
        //新增spuDetail
        SpuDetailDTO detailDTO = spuDTO.getSpuDetail();
        detailDTO.setSpuId(spu.getId());
        SpuDetail spuDetail = BeanHelper.copyProperties(detailDTO, SpuDetail.class);
        count = spuDetailMapper.insertSelective(spuDetail);
        if (1 != count) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

        //新增sku
        List<Sku> skus = BeanHelper.copyWithCollection(spuDTO.getSkus(), Sku.class);
        for (Sku sku : skus) {
            sku.setSpuId(spu.getId());
        }
        count = skuMapper.insertList(skus);
        if (count != skus.size()) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }

    /**
     * 商品上下架功能
     * @param id
     * @param saleable
     */
    @Override
    @Transactional
    public void updateSaleable(Long id, Boolean saleable) {
        //更新商品spu中的saleable
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        int count = goodsMapper.updateByPrimaryKeySelective(spu);
        if (1 != count) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        //更新商品sku中的enable
        Sku sku = new Sku();
        sku.setEnable(saleable);
        Example example = new Example(Sku.class);
        example.createCriteria().andEqualTo("spuId", id);
        count = skuMapper.updateByExampleSelective(sku, example);
        int skuSize = skuMapper.selectCountByExample(example);
        if (count != skuSize) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }

        //设置routingKey
        String key = saleable ? MQConstants.RoutingKey.ITEM_UP_KEY : MQConstants.RoutingKey.ITEM_DOWN_KEY;
        //发送消息
        amqpTemplate.convertAndSend(key, id);
    }

    /**
     * 修改商品->数据回显
     * 根据id查询SpuDetail
     * @param id
     * @return
     */
    @Override
    public SpuDetailDTO querySpuDetailBySpu(Long id) {
        SpuDetail spuDetail = spuDetailMapper.selectByPrimaryKey(id);
        if (null == spuDetail) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyProperties(spuDetail, SpuDetailDTO.class);
    }

    /**
     * 修改商品->数据回显
     * 根据spuId查询Skus
     * @param id
     * @return
     */
    @Override
    public List<SkuDTO> querySkuBySpu(Long id) {
        Sku sku = new Sku();
        sku.setSpuId(id);
        List<Sku> skus = skuMapper.select(sku);
        if (CollectionUtils.isEmpty(skus)) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        List<SkuDTO> skuDTOS = BeanHelper.copyWithCollection(skus, SkuDTO.class);
        return skuDTOS;
    }

    /**
     * 修改商品实现
     * @param spuDTO
     */
    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        //保存spu
        Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
        int count = goodsMapper.updateByPrimaryKeySelective(spu);
        if (1 != count) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }

        //保存spuDetail
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        SpuDetail spuDetail = BeanHelper.copyProperties(spuDetailDTO, SpuDetail.class);
        //spuDetail.setSpuId(spuDTO.getId());
        count = spuDetailMapper.updateByPrimaryKeySelective(spuDetail);
        if (1 != count) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }

        //删除旧sku
        Sku sku = new Sku();
        sku.setSpuId(spuDTO.getId());
        int skuSize = skuMapper.selectCount(sku);
        count = skuMapper.delete(sku);
        if (count != skuSize) {
            throw new LyException(ExceptionEnum.DELETE_OPERATION_FAIL);
        }

        //保存新sku
        List<SkuDTO> skuDTOS = spuDTO.getSkus();
        List<Sku> skus = BeanHelper.copyWithCollection(skuDTOS, Sku.class);
        for (Sku sku1 : skus) {
            sku1.setSpuId(spuDTO.getId());
        }
        count = skuMapper.insertList(skus);
        if (count != skus.size()) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }

    /**
     * 根据spu的id查询spu
     * 包括detail和skus
     * @param id
     * @return
     */
    @Override
    public SpuDTO querySpuById(Long id) {
        //查询spu
        Spu spu = goodsMapper.selectByPrimaryKey(id);
        SpuDTO spuDTO = BeanHelper.copyProperties(spu, SpuDTO.class);

        //查询detail
        SpuDetailDTO spuDetailDTO = querySpuDetailBySpu(id);
        spuDTO.setSpuDetail(spuDetailDTO);

        //查询skus
        List<SkuDTO> skus = querySkuBySpu(id);
        spuDTO.setSkus(skus);

        return spuDTO;
    }

    /**
     * 将categoryName和brandName封装进SpuDTO中
     * @param spuDTOS
     */
    private void handleCategoryAndBrand(List<SpuDTO> spuDTOS) {
        spuDTOS.forEach(spuDTO -> {
            String categoryName = categoryService.queryCategoryByIds(spuDTO.getCategoryIds()).stream()
                    .map(CategoryDTO::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(categoryName);

            BrandDTO brandDTO = brandService.queryBrandById(spuDTO.getBrandId());
            spuDTO.setBrandName(brandDTO.getName());
        });
    }
}
